package progetto1.csm.implementation;

import java.util.Random;

import progetto1.csm.core.SystemElement;
import progetto1.csm.core.actor.Element;
import progetto1.csm.core.actor.Watcher;
import sde.actor.Message;

public class Router extends Element {
	
	private static class Init extends Message{
		private Random random;
		private Element e0;
		private Element e1;
		private Element e2;
		private Element e3;
		private double q0,q1,q2,q3;
		
		private Init(Random random, Element e0, Element e1, Element e2,
				Element e3, double q0, double q1, double q2, double q3) {
			this.random = random;
			this.e0 = e0;
			this.e1 = e1;
			this.e2 = e2;
			this.e3 = e3;
			this.q0 = q0;
			this.q1 = q1;
			this.q2 = q2;
			this.q3 = q3;
		}		
	}

	protected Router(Watcher watcher, SystemElement element) {
		super(watcher, element);
	}
	
	private final byte CREATED=0, OPERATING=1;
	private Random random;
	private Element e0;
	private Element e1;
	private Element e2;
	private Element e3;
	private double q0,q1,q2,q3;
	
	protected void init(Random random, Element e0, Element e1, Element e2,
			Element e3, double q0, double q1, double q2, double q3) {
		send(new Init(random, e0, e1, e2, e3, q0, q1, q2, q3));
		become(CREATED);
	}
	
	@Override
	public void handler(Message m) {
		switch (currentStatus()) {
		case CREATED:
			if(m instanceof Init){
				Init i = (Init) m;
				this.random = i.random;
				this.e0 = i.e0;
				this.e1 = i.e1;
				this.e2 = i.e2;
				this.e3 = i.e3;
				this.q0 = i.q0;
				this.q1 = i.q1;
				this.q2 = i.q2;
				this.q3 = i.q3;
				become(OPERATING);
			}
			break;
		case OPERATING:
			if (m instanceof Arrival) {
				double p = random.nextDouble();
				if (p >= 0 && p < q0) {
					e0.send(m);
				} else if (p >= q0 && p < (q0+q1)) {
					e1.send(m);
				} else if (p >= (q0+q1) && p < (q0+q1+q2)) {
					e2.send(m);
				} else if (p >= (q0+q1+q2) && p <= (q0+q1+q2+q3)) {
					e3.send(m);
				} else{
					assert false;
				}
			}
			break;
		default:
			assert false;
			break;
		}
	}

}
